19. Seaborn库基础

本章概要

  • 学习材料:长三角门店客单价教学示例,字段为城市与客单价;全部可见输出标注“教学示例,非业务观测”。
  • 本章任务:运行 lst-seaborn-chartslst-seaborn-audit-output,绘制箱线图/小提琴图并计算五数、IQR边界及离群点。
  • 完成后你将得到:两种分布图、逐组五数概括、IQR边界、离群点列表/数量与两句分布解读。
  • 自我检查:用 quantile 手算箱体与离群点;组样本不足、字段缺失或示例数据被写成业务依据时先检查原因。
  • 拓展练习:把同一组统计和绘图方法应用到另一组长三角城市门店示例数据,并说明示例的适用范围。

Seaborn:基于Matplotlib的高级可视化库

Seaborn建立在Matplotlib之上,专为统计数据可视化而设计。

  • 更美观:默认样式更现代、更专业
  • 更简洁:更少代码即可实现复杂图表
  • 统计导向:内置统计图表类型(箱线图、小提琴图、热力图等)
  • 数据集支持:自带多个经典数据集(tips、titanic等)

运行前预测|泰坦尼克数据集分析

  • 输入预测:运行前先写出 titanic 的业务含义、数据类型或取值范围,并判断哪一个输入最可能改变结果。
  • 结果预测:不展开答案,先预测将得到titanic 的结果;同时写出方向、数量级或表格/图形结构。
  • 完成要求:能独立说明本任务从输入到“泰坦尼克数据集分析”结果的关键步骤,原样录入平台代码并得到可核对的运行结果。

⭐ 泰坦尼克数据集分析

# ⚠️ 平台原始代码 - 请原样输入至教学平台(注释除外),平台才会判定答案正确
import seaborn as sns  # 导入Seaborn可视化库
import matplotlib.pyplot as plt  # 导入Matplotlib绘图库
# 加载titanic数据集
titanic = sns.load_dataset("titanic")
# 使用catplot函数绘制柱状图
sns.catplot(x="class", y="survived", hue="sex", data=titanic, kind="bar")
# 设置标题
plt.subplots_adjust(top=0.9)
plt.suptitle("Survival rate by class and sex")  # 设置图形总标题
# 显示图形
plt.savefig("1.png")

任务复盘|泰坦尼克数据集分析

运行后核对:核对 titanic 是否按预测参与运算,实际输出是否与预测一致;若不一致,先检查类型、单位、索引/字段和运算顺序。

拓展练习:把数据替换为一个中国企业或市场序列,改变一个分组或时间窗口;说明图形结论是否改变,以及为何。

泰坦尼克代码解读

  • sns.load_dataset('titanic'):加载Seaborn内置的泰坦尼克数据集
  • sns.catplot():绘制分类数据图表
    • x='class':横轴为船舱等级
    • y='survived':纵轴为存活率
    • hue='sex':按性别分组着色
    • kind='bar':指定图表类型为柱状图

常用Seaborn图表:箱线图

箱线图(Boxplot) 展示数据的分布特征:

  • 箱体表示四分位数范围(Q1到Q3)
  • 箱内横线为中位数
  • 围栏为 \(Q1-1.5\times IQR\)\(Q3+1.5\times IQR\);触须到达围栏内最远观测
  • 超出范围的点标记为异常值
sns.boxplot(data=data, x='Category', y='Value1')

常用Seaborn图表:小提琴图

小提琴图(Violinplot) 是箱线图与核密度估计的结合:

  • 宽度表示数据在该值处的密度
  • 越宽表示出现频率越高
  • 可以发现多峰分布等特征
  • 比箱线图提供更多分布形状信息
sns.violinplot(data=data, x='Category', y='Value1')

常用Seaborn图表:热力图

热力图(Heatmap) 用于可视化矩阵数据,常用于相关性分析:

  • 颜色深浅表示数值大小
  • annot=True:在格子中显示数值
  • cmap='coolwarm':冷暖色方案(蓝=负相关,红=正相关)
corr = data[['Value1', 'Value2']].corr()
sns.heatmap(corr, annot=True, cmap='coolwarm')

常用Seaborn图表:回归散点图

回归散点图(Regplot) 结合散点图和线性回归拟合:

  • 自动计算并绘制线性回归线
  • 绘制95%置信区间(半透明阴影)
  • 直观判断变量关系强度和拟合优度
sns.regplot(data=data, x='Value1', y='Value2')

图表综合演示:分布比较

展开四类图表的离线输入与绘图代码
import numpy as np  # 导入数值库以执行有限值与分位数核对
import pandas as pd  # 导入表格库以组织长三角门店示例数据
import seaborn as sns  # 导入统计绘图库以绘制两种分布图
import matplotlib.pyplot as plt  # 导入基础绘图库以控制双面板
data=pd.DataFrame({'城市':['上海']*8+['杭州']*8,'客单价':[86,91,95,98,102,108,112,180,72,76,79,83,88,92,96,135]})  # 建立确定性门店客单价教学示例
assert data.groupby('城市').size().min()>=8 and np.isfinite(data['客单价']).all()  # 执行组样本量与有限值输入要求
summary=data.groupby('城市')['客单价'].describe(percentiles=[.25,.5,.75])[['min','25%','50%','75%','max']]  # 计算逐组五数概括
quartiles=data.groupby('城市')['客单价'].quantile([.25,.75]).unstack()  # 提取逐组Q1与Q3
quartiles.columns=['Q1','Q3']  # 统一分位数字段名
quartiles['IQR']=quartiles['Q3']-quartiles['Q1']  # 计算四分位距
quartiles['下界']=quartiles['Q1']-1.5*quartiles['IQR']  # 计算IQR离群下界
quartiles['上界']=quartiles['Q3']+1.5*quartiles['IQR']  # 计算IQR离群上界
audited=data.join(quartiles[['下界','上界']],on='城市')  # 把逐组边界回连到每条记录
outliers=audited.loc[(audited['客单价']<audited['下界'])|(audited['客单价']>audited['上界']),['城市','客单价']]  # 提取离群点列表
fig,axes=plt.subplots(1,2,figsize=(11,4.2))  # 创建箱线图与小提琴图双面板
sns.boxplot(data=data,x='城市',y='客单价',ax=axes[0])  # 绘制分类箱线图
sns.violinplot(data=data,x='城市',y='客单价',inner='quartile',cut=0,ax=axes[1])  # 绘制含四分位线的小提琴图
axes[0].set_title('箱线图|教学示例,非业务观测',fontsize=16)  # 在箱线图内持续标明依据身份
axes[1].set_title('小提琴图|教学示例,非业务观测',fontsize=16)  # 在小提琴图内持续标明依据身份
for ax in axes: ax.set(xlabel='城市门店组',ylabel='客单价(元)')  # 统一两图业务轴与单位
plt.tight_layout(); plt.show()  # 显示两种分布图
Listing 1: 长三角门店客单价箱线图与小提琴图|教学示例,非业务观测
教学示例,非业务观测。左侧箱线图和右侧小提琴图比较上海与杭州门店客单价,并配套五数概括、IQR边界和离群点检查。

分布检查|教学示例,非业务观测

Listing 2
展开五数、IQR边界与离群点输出代码
print('教学示例,非业务观测|五数概括\n'+summary.round(2).to_string())  # 紧凑输出逐组min、Q1、median、Q3与max
print('\nIQR上下界\n'+quartiles.round(2).to_string())  # 紧凑输出逐组IQR与上下界
print('\n离群点列表:',outliers.to_dict('records'),';数量:',len(outliers))  # 输出离群点对象与总数
教学示例,非业务观测|五数概括
     min    25%    50%    75%    max
城市                                  
上海  86.0  94.00  100.0  109.0  180.0
杭州  72.0  78.25   85.5   93.0  135.0

IQR上下界
       Q1     Q3    IQR     下界      上界
城市                                    
上海  94.00  109.0  15.00  71.50  131.50
杭州  78.25   93.0  14.75  56.12  115.12

离群点列表: [{'城市': '上海', '客单价': 180}, {'城市': '杭州', '客单价': 135}] ;数量: 2

图表综合演示:关系核对

展开关系核对绘图代码
relation_data=pd.DataFrame({'Value1':[1,2,3,4,5,6,7,8],'Value2':[1.4,2.1,2.8,4.2,4.7,6.1,6.6,8.3]})  # 建立确定性关系教学示例以解除前块变量依赖
fig, axes = plt.subplots(1, 2, figsize=(11, 4.2))  # 创建关系核对双面板

# 子图3:热力图
corr = relation_data[['Value1', 'Value2']].corr()  # 计算示例数据关系矩阵
sns.heatmap(corr, annot=True, annot_kws={'size':16}, cmap='coolwarm', ax=axes[0])
axes[0].set_title('相关性热力图|教学示例,非业务观测', fontsize=16)

# 子图4:散点图带回归线
sns.regplot(data=relation_data, x='Value1', y='Value2', ax=axes[1])
axes[1].set_title('散点图与回归线|教学示例,非业务观测', fontsize=16)

plt.tight_layout()
plt.show()
Listing 3: 关系热力图与回归散点图|教学示例,非业务观测
教学示例,非业务观测。左侧热力图显示两个示例数据变量的相关系数,右侧散点图显示同一示例数据的线性拟合方向。

Seaborn内置样式

sns.set_style() 设置图表的整体风格:

样式名称 特点 适用场景
whitegrid 白色背景 + 网格 数据展示(推荐)
darkgrid 深色背景 + 网格 深色主题
white 纯白背景 简洁风格
dark 深色背景 护眼模式
ticks 白色背景 + 刻度线 学术论文

Seaborn配色方案

sns.set_palette() 设置图表颜色循环:

  • 'husl':均匀色彩空间,区分度高
  • 'pastel':柔和粉彩色系
  • 'dark':深色调
  • 'colorblind':色盲友好配色
  • 'Set1''Set2':Matplotlib内置配色

多维散点图:样式与配色实战

展开样式、配色与离线散点图代码
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

# 设置样式和配色
sns.set_style('whitegrid')
sns.set_palette('husl')
plt.rcParams['font.sans-serif'] = ['Source Han Serif SC']  # Seaborn 重置样式后重新绑定已安装中文字体
plt.rcParams['axes.unicode_minus'] = False  # 保持坐标轴负号正确显示

fig, ax = plt.subplots(figsize=(10, 3.8))

# 使用离线中性示例数据,避免渲染依赖 Seaborn 在线数据仓库
data_plot = pd.DataFrame({
    'total_bill': [10.5, 13.2, 18.7, 21.4, 24.8, 28.1, 31.6, 35.2],
    'tip': [1.6, 2.0, 2.7, 3.1, 3.8, 4.2, 4.8, 5.3],
    'day': ['Thur', 'Thur', 'Fri', 'Fri', 'Sat', 'Sat', 'Sun', 'Sun'],
    'size': [2, 2, 2, 3, 3, 4, 4, 5],
})

# 绘制多维散点图:颜色=星期,大小=人数
sns.scatterplot(data=data_plot, x='total_bill', y='tip', hue='day', size='size', ax=ax)

ax.set_title('餐厅小费映射|教学示例,非业务观测', fontsize=16)
ax.set_xlabel('总账单', fontsize=16)
ax.set_ylabel('小费', fontsize=16)
ax.legend(title='星期', loc='center left', bbox_to_anchor=(1.01, 0.5), frameon=True)  # 将图例移出坐标区,避免遮挡高值点与刻度
fig.tight_layout(rect=(0, 0, 0.82, 1))  # 为外置图例预留右侧空间
plt.show()
Listing 4: Seaborn样式设置示例|教学示例,非业务观测
教学示例,非业务观测。散点图用账单、小费、星期和人数示例数据演示颜色与尺寸映射。

散点图代码解读

sns.scatterplot() 支持多维数据映射:

  • x='total_bill':横轴为总账单金额
  • y='tip':纵轴为小费金额
  • hue='day':按星期着色,不同颜色表示不同日期
  • size='size':按人数映射点的大小

从图中可以观察到:总账单与小费呈正相关,周末小费比例可能不同。

本章小结

  • Seaborn是基于Matplotlib的高级统计可视化库
  • 四种核心图表:箱线图、小提琴图、热力图、回归散点图
  • set_style() 控制图表风格,set_palette() 控制配色
  • huesize 参数实现多维数据映射
  • Seaborn内置多个经典数据集,方便学习和演示

随堂练习

  • 问题 1|需要准备哪些数据?:长三角门店客单价教学示例;城市、客单价字段完整,每组至少8条且数值有限。
  • 问题 2|需要完成哪些操作?:运行 lst-seaborn-chartslst-seaborn-audit-output,生成两图、五数、IQR边界与离群点检查。
  • 问题 3|应得到哪些结果?:min/Q1/median/Q3/max、IQR上下界、离群点列表/数量及两种图形均可见。
  • 问题 4|怎样确认结果可靠?:用 quantile 和1.5×IQR逐组复算;小样本、缺失或示例数据被写成业务事实时先检查原因。
  • 问题 5|换一个情境,怎样继续应用?:把同一组方法应用到另一组长三角城市门店示例数据,并保留“教学示例,非业务观测”标识。
  • 作答提示:请依次写清所用数据、分析过程、所得结果、核对方法和拓展思考。课程所需数据见前言中的下载入口;教学平台固定题按页面说明完成。

教师参考解答|答案与说明 1

  • 补充练习|箱线图、小提琴图与完整离群检查

教师参考解答|代码 1

展开代码(代码区可独立滚动)
import matplotlib.pyplot as plt  # 导入绘图库以生成教师答案图
import numpy as np  # 导入数值库以执行有限值核对
import pandas as pd  # 导入表格库以组织逐组检查
import seaborn as sns  # 导入统计绘图库以生成箱线图与小提琴图
sample=pd.DataFrame({'城市':['上海']*8+['杭州']*8,'客单价':[86,91,95,98,102,108,112,180,72,76,79,83,88,92,96,135]})  # 重新计算长三角门店教学示例
assert sample.groupby('城市').size().min()>=8 and np.isfinite(sample['客单价']).all()  # 执行组样本量与数值要求
five=sample.groupby('城市')['客单价'].describe(percentiles=[.25,.5,.75])[['min','25%','50%','75%','max']]  # 计算min/Q1/median/Q3/max
bounds=sample.groupby('城市')['客单价'].quantile([.25,.75]).unstack().set_axis(['Q1','Q3'],axis=1)  # 提取逐组四分位数
bounds['IQR']=bounds['Q3']-bounds['Q1']  # 计算逐组IQR
bounds['下界']=bounds['Q1']-1.5*bounds['IQR']  # 计算逐组离群下界
bounds['上界']=bounds['Q3']+1.5*bounds['IQR']  # 计算逐组离群上界
checked=sample.join(bounds[['下界','上界']],on='城市')  # 回连逐组边界
outliers=checked.loc[(checked['客单价']<checked['下界'])|(checked['客单价']>checked['上界']),['城市','客单价']]  # 提取离群点列表
fig,axes=plt.subplots(1,2,figsize=(10,4))  # 创建教师答案双面板
sns.boxplot(data=sample,x='城市',y='客单价',ax=axes[0])  # 生成箱线图
sns.violinplot(data=sample,x='城市',y='客单价',inner='quartile',cut=0,ax=axes[1])  # 生成小提琴图
axes[0].set_title('箱线图|教学示例,非业务观测'); axes[1].set_title('小提琴图|教学示例,非业务观测')  # 在两图内标明示例数据身份
plt.tight_layout(); plt.show()  # 显示教师答案图形
assert set(map(tuple,outliers.to_numpy()))=={('上海',180),('杭州',135)} and len(outliers)==2  # 独立检查离群列表与数量
print('教学示例,非业务观测',{'五数概括':five.round(2).to_dict(),'IQR边界':bounds.round(2).to_dict(),'离群点':outliers.to_dict('records'),'离群数量':len(outliers)})  # 显示五数概括、IQR边界和离群点结果

教师参考解答|答案与说明 2

  • 解释与拓展应用答案:箱线图便于比较中位数、IQR与离群点;小提琴图补充分布密度形状。示例数据只能说明方法,离群不等于错误,也不支持真实门店经营结论。

  • 所用数据与字段:长表字段“城市”、“客单价”;按城市报告组样本量

  • 参考代码或推导(平台保护块之外):

教师参考解答|代码 2

展开代码(代码区可独立滚动)
alternative_case=pd.DataFrame({'城市':['南京']*8+['宁波']*8,'客单价':[68,71,74,77,80,84,89,128,75,79,82,86,90,94,99,142]})  # 建立另一组长三角门店教学示例
assert alternative_case.groupby('城市').size().min()>=8 and np.isfinite(alternative_case['客单价']).all()  # 检查新案例组样本量与数值
m_five=alternative_case.groupby('城市')['客单价'].describe(percentiles=[.25,.5,.75])[['min','25%','50%','75%','max']]  # 计算新案例五数概括
m_bounds=alternative_case.groupby('城市')['客单价'].quantile([.25,.75]).unstack().set_axis(['Q1','Q3'],axis=1)  # 提取新案例四分位数
m_bounds['IQR']=m_bounds['Q3']-m_bounds['Q1']  # 计算新案例IQR
m_bounds['下界']=m_bounds['Q1']-1.5*m_bounds['IQR']  # 计算新案例下界
m_bounds['上界']=m_bounds['Q3']+1.5*m_bounds['IQR']  # 计算新案例上界
m_checked=alternative_case.join(m_bounds[['下界','上界']],on='城市')  # 把上下界补充到新案例数据中
m_outliers=m_checked.loc[(m_checked['客单价']<m_checked['下界'])|(m_checked['客单价']>m_checked['上界']),['城市','客单价']]  # 提取新案例离群点
fig,axes=plt.subplots(1,2,figsize=(10,4))  # 创建新案例双面板
sns.boxplot(data=alternative_case,x='城市',y='客单价',ax=axes[0]); sns.violinplot(data=alternative_case,x='城市',y='客单价',inner='quartile',cut=0,ax=axes[1])  # 生成新案例箱线图与小提琴图
axes[0].set_title('箱线图|教学示例,非业务观测'); axes[1].set_title('小提琴图|教学示例,非业务观测')  # 持续标明新案例依据身份
plt.tight_layout(); plt.show()  # 显示新案例图形
assert len(m_outliers)==2 and set(m_outliers['城市'])=={'南京','宁波'}  # 核对每个新案例城市各有一个上侧离群点
print('教学示例,非业务观测',{'新案例对象':'南京与宁波门店','五数概括':m_five.round(2).to_dict(),'IQR边界':m_bounds.round(2).to_dict(),'离群点':m_outliers.to_dict('records'),'离群数量':len(m_outliers)})  # 输出新案例完整检查

教师参考解答|答案与说明 3

  • 参考结果:箱线图、小提琴图、逐组五数概括、IQR上下界、离群点列表/数量及用同样方法应用
  • 边界 / 局限:小样本示例数据只作方法示范;离群点需要业务核验,不能自动删除或解释为异常经营
  • 常见错误:把触须端点当min/max;用全样本边界替代逐组边界;只报数量不报离群值;漏写示例数据身份